package cn.zzdt4j.auth.security;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

import static cn.zzdt4j.auth.constant.Constants.STEP;
import static cn.zzdt4j.auth.constant.Constants.TOKEN_VALIDITY_IN_SECONDS;
import static cn.zzdt4j.auth.toolkit.JwtTokenUtil.SECRET;
import static cn.zzdt4j.common.constant.Constants.AUTHORITIES_KEY;

/**
 * Jwt token manager.
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023 /10/29 22:58
 */
@Component
public class JwtTokenManager {


    /**
     * Create token.
     *
     * @param userName the user name
     * @return new token
     */
    public String createToken(String userName) {
        long now = System.currentTimeMillis();
        Date validity;
        validity = new Date(now + TOKEN_VALIDITY_IN_SECONDS * STEP);
        Claims claims = Jwts.claims().setSubject(userName);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    /**
     * Validate token.
     *
     * @param token the token
     */
    public void validateToken(String token) {
        Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
    }

    /**
     * Gets auth info.
     *
     * @param token the token
     * @return the authentication
     */
    public Authentication getAuthentication(String token) {
        final Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        final List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
        final User principal = new User(claims.getSubject(), StrUtil.EMPTY, authorities);
        return new UsernamePasswordAuthenticationToken(principal, StrUtil.EMPTY, authorities);
    }
}
